package 队列;

import java.util.Arrays;

/**
 * @Description 队列
 * 队列是一个有序列表，可以用数组或是链表来实现。
 * 遵循先入先出的原则。即：先存入队列的数据，要先取出。后存入的要后取出
 * <p>
 * 数组模拟队列 (已优化为环形队列)
 * 队列本身是有序列表，若使用数组的结构来存储队列的数据，
 * 则队列数组的声明如图, 其中 maxSize 是该队列的最大容量。
 * 因为队列的输出、输入是分别从前后端来处理，因此
 * 需要两个变量 front 及 tail 分别记录队列前后端的下标，front 会随着数据输出而改变，
 * 而 rear则是随着数据输入而改变
 * @Author 俊昭
 * @Date 2022/4/26
 * @since v1.0 2022/4/26 基本实现功能
 * @since v1.1 2022/4/26 优化显示
 * @since v1.2 2022/4/26 改善代码并 丰满show功能
 */
public class CircleQueue {
    // 记录队列头尾
    private int front = - 1;
    private int tail = - 1;
    private int i = 0;
    // 队列最大容量
    private int maxSize;
    // 数组队列初始化
    private String[] arrQueue;

    // 初始化
    public CircleQueue(int size) {
        this.maxSize = size;
        arrQueue = new String[maxSize];
        Arrays.fill(arrQueue, "空位");
    }

    // 入队列
    public void addQueue() {
        if (havePlace()) {
            tail++;
            i++;
            arrQueue[tail % maxSize] = i + " " + Math.round(Math.random() * (100 - 1) + 1);
            System.out.print(arrQueue[tail % maxSize] + "入 ");

        }

    }

    // 出队列
    public void getQueue() {
        if (! isEmpty()) {
            front++;
            System.out.print(arrQueue[front % maxSize] + "出 ");
            arrQueue[front % maxSize] = "空位";

        }
    }

    // 查看队列
    public void show() {
        int t = tail + 1;
        int f = front + 1;
        System.out.println("入 指针" + t + " " + t % maxSize);
        System.out.println("出 指针" + f + " " + f % maxSize);
    }

    /**
     * @return true如果有位置 反之false
     * @description 判断是否有位置
     * @author 俊昭
     * @date 2022/4/27
     */
    public boolean havePlace() {
        return ! ((tail + 1) % maxSize == front % maxSize);
    }

    /**
     * @return true 如果为空 反之false
     * @description 判断是否为空
     * @author 俊昭
     * @date 2022/4/27
     */
    public boolean isEmpty() {
        return tail % maxSize == front % maxSize;
    }

    public String[] getArrQueue() {
        return arrQueue;
    }
}

class QueueTest {
    public static void main(String[] args) {
        CircleQueue circleQueue = new CircleQueue(50);
        int times1;
        int times2;

        for (int x = 0; x < 100; x++) {
            // 执行随机次数
            times1 = Math.toIntExact(Math.round(Math.random() * (10 - 1) + 1));
            times2 = Math.toIntExact(Math.round(Math.random() * (10 - 1) + 1));

            for (int i = 0; i < times1; i++) {
                circleQueue.addQueue();
            }
            System.out.println();
            for (int i = 0; i < times2; i++) {
                circleQueue.getQueue();
            }
            System.out.println();
            System.out.println(Arrays.toString(circleQueue.getArrQueue()));
            circleQueue.show();
            System.out.println();
        }

//            circleQueue.show();

    }
}